﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using CarbonExchange.Bll;

namespace CarbonExchange.Tests
{
    [TestClass]
    public class SiteQuestionTest : BaseTest
    {
        [TestMethod]
        public void SiteQuestion_GetById_WithIncorrectId_ReturnsNull()
        {
            SiteQuestionFactory factory = new SiteQuestionFactory(_Context);
            Assert.IsNull(factory.GetById(int.MaxValue));
        }

        [TestMethod]
        public void SiteQuestion_GetById_WithCorrectId_ReturnsNotNull()
        {
            SiteQuestionFactory factory = new SiteQuestionFactory(_Context);
            Assert.IsNotNull(factory.GetById(_TestSiteQuestions[0].Id));
        }

        [TestMethod]
        public void SiteQuestion_GetById_WithCorrectId_PopulatesCorrectly()
        {
            SiteQuestionFactory factory = new SiteQuestionFactory(_Context);
            var tmp = factory.GetById(_TestSiteQuestions[0].Id);
            Assert.IsNotNull(tmp);
            Assert.AreEqual(_TestSiteQuestions[0].Id, tmp.Id);
            Assert.AreEqual(_TestSiteQuestions[0].QuestionId, tmp.QuestionId);
            Assert.AreEqual(_TestSiteQuestions[0].Question.QuestionName, tmp.QuestionName);
            Assert.AreEqual(_TestSite.Id, tmp.SiteId);
            Assert.AreEqual(_TestSiteQuestions[0].Created.ToLocalTime(), tmp.Created);
            Assert.AreEqual(_TestSiteQuestions[0].Sequence, tmp.Sequence);
            Assert.AreEqual(_TestSiteQuestions[0].Question.SectionId, tmp.SectionId);
            Assert.AreEqual(_TestSiteQuestions[0].Question.Section.Name, tmp.SectionName);
        }

        [TestMethod]
        public void SiteQuestion_GetAllBySectionId_WithInCorrectId_ReturnsEmptyList()
        {
            SiteQuestionFactory factory = new SiteQuestionFactory(_Context);
            var tmp = factory.GetAllBySectionId(int.MaxValue, _TestSite.Id);
            Assert.IsNotNull(tmp);
            Assert.AreEqual(0, tmp.Count());
        }

        [TestMethod]
        public void SiteQuestion_GetAllBySectionId_WithCorrectId_ReturnsPopulatedList()
        {
            SiteQuestionFactory factory = new SiteQuestionFactory(_Context);
            Assert.AreEqual(_TestSiteQuestions.Count(), factory.GetAllBySectionId(_TestSections[0].Id, _TestSite.Id).Count());

            _TestQuestions[1].Section = _TestSections[1];
            _Context.SubmitChanges();
            Assert.AreEqual(_TestSiteQuestions.Count() - 1, factory.GetAllBySectionId(_TestSections[0].Id, _TestSite.Id).Count());
            Assert.AreEqual(1, factory.GetAllBySectionId(_TestSections[1].Id, _TestSite.Id).Count());
        }

        [TestMethod]
        public void SiteQuestion_GetAllBySectionId_WithCorrectId_ReturnsPopulatesCorrectly()
        {
            SiteQuestionFactory factory = new SiteQuestionFactory(_Context);
            var tmpList = factory.GetAllBySectionId(_TestSections[0].Id, _TestSite.Id).ToList();
            var tmp = tmpList[0];
            Assert.IsNotNull(tmp);
            Assert.AreEqual(_TestSiteQuestions[0].Id, tmp.Id);
            Assert.AreEqual(_TestSiteQuestions[0].QuestionId, tmp.QuestionId);
            Assert.AreEqual(_TestSiteQuestions[0].Question.QuestionName, tmp.QuestionName);
            Assert.AreEqual(_TestSite.Id, tmp.SiteId);
            Assert.AreEqual(_TestSiteQuestions[0].Created.ToLocalTime(), tmp.Created);
            Assert.AreEqual(_TestSiteQuestions[0].Sequence, tmp.Sequence);
            Assert.AreEqual(_TestSiteQuestions[0].Question.SectionId, tmp.SectionId);
            Assert.AreEqual(_TestSiteQuestions[0].Question.Section.Name, tmp.SectionName);
        }

        [TestMethod]
        public void SiteQuestion_GetAllBySiteId_WithCorrectId_ReturnsPopulatesCorrectly()
        {
            SiteQuestionFactory factory = new SiteQuestionFactory(_Context);
            Assert.AreEqual(_TestSiteQuestions.Count, factory.GetAllBySiteId(_TestSite.Id).ToList().Count());
            _TestSiteQuestions[0].SiteId = _AlternateSite.Id;
            _Context.SubmitChanges();
            Assert.AreEqual(_TestSiteQuestions.Count - 1, factory.GetAllBySiteId(_TestSite.Id).ToList().Count());
            Assert.AreEqual(1, factory.GetAllBySiteId(_AlternateSite.Id).ToList().Count());
        }

        [TestMethod]
        public void SiteQuestion_DeleteOne()
        {
            SiteQuestionFactory factory = new SiteQuestionFactory(_Context);
            Assert.AreEqual(_TestSiteQuestions.Count, factory.GetAllBySiteId(_TestSite.Id).ToList().Count());
            factory.Delete(factory.GetAllBySiteId(_TestSite.Id).First());
            Assert.AreEqual(_TestSiteQuestions.Count - 1, factory.GetAllBySiteId(_TestSite.Id).ToList().Count());
        }

        [TestMethod]
        public void SiteQuestion_DeleteMany()
        {
            SiteQuestionFactory factory = new SiteQuestionFactory(_Context);
            Assert.AreEqual(_TestSiteQuestions.Count, factory.GetAllBySiteId(_TestSite.Id).ToList().Count());
            factory.Delete(factory.GetAllBySiteId(_TestSite.Id));
            Assert.AreEqual(0, factory.GetAllBySiteId(_TestSite.Id).ToList().Count());
        }

        [TestMethod]
        public void SiteQuestion_InsertOne()
        {
            SiteQuestionFactory factory = new SiteQuestionFactory(_Context);
            var tmp = new SiteQuestion(_AlternateSite.Id, _TestQuestions[1].Id);
            DateTime expectedCreated = DateTime.Now;
            int expectedSequence = factory.GetAllBySectionId(_TestQuestions[1].SectionId, _AlternateSite.Id).Count();
            
            factory.Save(tmp);

            Assert.IsTrue(tmp.Id > 0);
            Assert.IsTrue(expectedCreated - tmp.Created < TimeSpan.FromSeconds(1));
            Assert.AreEqual(_TestQuestions[1].Id, tmp.QuestionId);
            Assert.AreEqual(_TestQuestions[1].QuestionName, tmp.QuestionName);
            Assert.AreEqual(_TestQuestions[1].SectionId, tmp.SectionId);
            Assert.AreEqual(_TestQuestions[1].Section.Name, tmp.SectionName);
            Assert.AreEqual(expectedSequence, tmp.Sequence);
            Assert.AreEqual(_AlternateSite.Id, tmp.SiteId);

            var tmp2 = factory.GetById(tmp.Id);
            Assert.IsNotNull(tmp2);
            Assert.AreEqual(tmp2.Id, tmp.Id);
            Assert.AreEqual(tmp2.Created, tmp.Created);
            Assert.AreEqual(tmp2.QuestionId, tmp.QuestionId);
            Assert.AreEqual(tmp2.QuestionName, tmp.QuestionName);
            Assert.AreEqual(tmp2.SectionId, tmp.SectionId);
            Assert.AreEqual(tmp2.SectionName, tmp.SectionName);
            Assert.AreEqual(tmp2.Sequence, tmp.Sequence);
            Assert.AreEqual(tmp2.SiteId, tmp.SiteId);
        }

        [TestMethod]
        public void SiteQuestion_InsertMany()
        {
            int noToGen = 3;
            SiteQuestionFactory factory = new SiteQuestionFactory(_Context);
            List<SiteQuestion> created = new List<SiteQuestion>();
            for (int i = 0; i < noToGen; i++)
            {
                created.Add(new SiteQuestion(_AlternateSite.Id, _TestQuestions[i].Id));
            }
            DateTime expectedCreated = DateTime.Now;
            factory.Save(created);
            foreach (var tmp in created)
            {
                Assert.IsTrue(tmp.Id > 0);
                Assert.IsTrue(expectedCreated - tmp.Created < TimeSpan.FromSeconds(1));
                Assert.AreEqual(_TestQuestions[created.IndexOf(tmp)].Id, tmp.QuestionId);
                Assert.AreEqual(_TestQuestions[created.IndexOf(tmp)].QuestionName, tmp.QuestionName);
                Assert.AreEqual(_TestQuestions[created.IndexOf(tmp)].SectionId, tmp.SectionId);
                Assert.AreEqual(_TestQuestions[created.IndexOf(tmp)].Section.Name, tmp.SectionName);
                Assert.AreEqual(created.IndexOf(tmp), tmp.Sequence);
                Assert.AreEqual(_AlternateSite.Id, tmp.SiteId);
            }

            var tmpList = factory.GetAllBySiteId(_AlternateSite.Id).ToList();
            Assert.AreEqual(tmpList.Count(), created.Count());
            foreach (var tmp in created)
            {
                var tmp2 = tmpList.ElementAt(created.IndexOf(tmp));
                Assert.AreEqual(tmp2.Id, tmp.Id);
                Assert.AreEqual(tmp2.Created, tmp.Created);
                Assert.AreEqual(tmp2.QuestionId, tmp.QuestionId);
                Assert.AreEqual(tmp2.QuestionName, tmp.QuestionName);
                Assert.AreEqual(tmp2.SectionId, tmp.SectionId);
                Assert.AreEqual(tmp2.SectionName, tmp.SectionName);
                Assert.AreEqual(tmp2.Sequence, tmp.Sequence);
                Assert.AreEqual(tmp2.SiteId, tmp.SiteId);
            }

        }

        [TestMethod]
        public void SiteQuestion_InsertMany_SetsSequenceCorrectly()
        {
            SiteQuestionFactory factory = new SiteQuestionFactory(_Context);
            
            List<SiteQuestion> created = new List<SiteQuestion>();
            _TestQuestions[1].Section = _TestSections[1];
            
            _Context.SubmitChanges();

            created.Add(new SiteQuestion(_AlternateSite.Id, _TestQuestions[0].Id));
            created.Add(new SiteQuestion(_AlternateSite.Id, _TestQuestions[1].Id));
            created.Add(new SiteQuestion(_AlternateSite.Id, _TestQuestions[2].Id));
            
            factory.Save(created);
            
            Assert.AreEqual(0, created[0].Sequence);
            Assert.AreEqual(0, created[1].Sequence);
            Assert.AreEqual(1, created[2].Sequence);

            _TestQuestions[1].Section = _TestSections[0];

            _Context.SubmitChanges();

            created.Add(new SiteQuestion(_TestSite.Id, _TestQuestions[0].Id));

            factory.Save(created);

            Assert.AreEqual(3, created[3].Sequence);

            Assert.AreEqual(created[3].Id, factory.GetAllBySectionId(_TestSections[0].Id, _TestSite.Id).ToArray().Last().Id);
        }
    }
}
